#include "mainwindow.h"

#include "login.h"
#include "mainwidget.h"
#include "chatwindow.h"
#include "configdialog.h"
#include "registrationdialog.h"

#include "client.h"

#include <QAction>
#include <QMenu>
#include <QMenuBar>
#include <QCoreApplication>
#include <QMessageBox>
#include <QCloseEvent>

//This function should be in common/status.h, but it doesn't compile there
QString statusToString(Status status){
	switch(status){
		case Online:
			return "Online";
		case Away:
			return "Away";
		case Offline:
			return "Offline";
		case Inactivity:
			return "Inactive";
		default:
			return "";
	}
}

namespace Ui {

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), mainWidget(0) {

	quitAction = new QAction(tr("&Quit"), this);
	connect(quitAction, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()));
	disconnectAction = new QAction(tr("&Disconnect"), this);
	connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnect()));
	restoreAction = new QAction(tr("&Restore"), this);
	restoreAction->setEnabled(false);
	connect(restoreAction, SIGNAL(triggered()), this, SLOT(restore()));
	configAction = new QAction(tr("&Preferences"), this);
	connect(configAction, SIGNAL(triggered()), this, SLOT(config()));
	registrationAction = new QAction(tr("Re&gistration"), this);
	connect(registrationAction, SIGNAL(triggered()), this, SLOT(registration()));

	windowMenu = new QMenu(tr("&Tuim"),this);
	windowMenu->addAction(configAction);
	windowMenu->addAction(registrationAction);
	windowMenu->addSeparator();
	windowMenu->addAction(disconnectAction);
	windowMenu->addAction(quitAction);
	menuBar()->addMenu(windowMenu);

	disconnected();

	systrayMsg=true;
	createTrayIcon();
	host="127.0.0.1";
	port=1234;
	inactivityTime=0;

	client=0;

	setWindowTitle("tuim client");

	config();
}

MainWindow::~MainWindow() {
	if(restoreAction) delete restoreAction;
	if(configAction) delete configAction;
	if(quitAction) delete quitAction;
	if(disconnectAction) delete disconnectAction;
	if(windowMenu) delete windowMenu;
	if(trayIconMenu) delete trayIconMenu;
	if(trayIcon) delete trayIcon;
}

void MainWindow::createLogin(){
	login = new Login(this);
	connect(login,SIGNAL(tryToConnect(const QString&,const QString&)),this,SLOT(tryToConnect(const QString&,const QString&)));
	connect(login,SIGNAL(cancelConnection()),this,SLOT(cancelConnection()));
	setCentralWidget(login);
}

void MainWindow::createTrayIcon(){
	trayIconMenu = new QMenu(this);
	trayIconMenu->addAction(restoreAction);
	trayIconMenu->addSeparator();
	trayIconMenu->addAction(disconnectAction);
	trayIconMenu->addAction(quitAction);

	trayIcon = new QSystemTrayIcon(this);
	trayIcon->setContextMenu(trayIconMenu);
	trayIcon->setIcon(QIcon("data/img/chat.png"));
	trayIcon->show();
	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
}

void MainWindow::friendEnteredMessage(const QString &friend_){
	trayIcon->showMessage("Friend entered",friend_ + " is now Online");
}

void MainWindow::friendChangedStatusMessage(const QString &friend_, Status current){
	trayIcon->showMessage("Friend changed status",friend_ + " became " +statusToString(current));
}

void MainWindow::closeEvent(QCloseEvent *event){
	if(systrayMsg){
		QMessageBox::information(this, tr("Systray"),tr("TUIM will keep running in the system tray. To terminate it, choose <b>Quit</b> in the context menu of the system tray entry. You won't see this message anymore."));
		systrayMsg=false;
	}
	restoreAction->setEnabled(true);
	hide();
	event->ignore();
}

void MainWindow::createProtocolConnects() {
	/* Incomming messages */
	/* Conection messages */
	connect(client, SIGNAL(CAccepted(Friend *)), this, SLOT(connected(Friend *)));
	connect(client, SIGNAL(CDenied()), this, SLOT(refused()));
	connect(client, SIGNAL(CDenied()), this->login, SLOT(refused()));

	/* User messages */
	connect(client, SIGNAL(UFFriendsList(QList<Friend *>)), this->mainWidget, SLOT(loadFriends(QList<Friend *>)));
	connect(client, SIGNAL(UFFriendStatusChanged(Friend *, QList<int> )), this->mainWidget, SLOT(friendStatusChanged(Friend *, QList<int> )));

	/* Chat messages */
	connect(client, SIGNAL(HFStarted(Chat *)), this->mainWidget, SLOT(newChatWindow(Chat *)));
	connect(client, SIGNAL(HFSent(Chat*, Friend*, const QString&)), this->mainWidget, SLOT(newMessageIncoming(Chat*, Friend*, const QString&)));
	connect(client, SIGNAL(HFExited(Chat*, Friend*)), this->mainWidget, SLOT(friendExit(Chat*, Friend*)));
	connect(client, SIGNAL(HFEntered(Chat*, Friend*)), this->mainWidget, SLOT(newFriendChat(Chat*, Friend*)));
	connect(client, SIGNAL(HFTerminated(Chat*)), this->mainWidget, SLOT(chatTerminated(Chat*)));

	/* Friend messages */
	connect(client, SIGNAL(FFInvitation(const QString &)), this->mainWidget, SLOT(friendInvitation(const QString &)));
	connect(client, SIGNAL(FFAddition(Friend *)), this->mainWidget, SLOT(friendAddition(Friend *)));
	connect(client, SIGNAL(FFDenial(const QString &)), this->mainWidget, SLOT(friendDenial(const QString &)));
	connect(client, SIGNAL(FFRemoval(Friend *, QList<int>)), this->mainWidget, SLOT(friendRemoval(Friend *, QList<int>)));

	/* Outcomming messages */
	/* Chat messages */
	connect(mainWidget, SIGNAL(startChat(int)), client, SLOT(startChat(int)));
	connect(mainWidget, SIGNAL(inviteChat(Chat*,int)), client, SLOT(inviteChat(Chat*, int)));
	connect(mainWidget, SIGNAL(quitChat(Chat *)), client, SLOT(quitChat(Chat *)));
	connect(mainWidget, SIGNAL(newOutcomingMessage(const QString&, Chat *)), client, SLOT(newOutcomingMessage(const QString&, Chat *)));

	/* User messages */
	connect(mainWidget, SIGNAL(statusChanged(Status)), this, SLOT(statusChanged(Status)));

	/* Friend messages */
	connect(mainWidget, SIGNAL(removeFriend(Friend *)), client, SLOT(removeFriend(Friend *)));
	connect(mainWidget, SIGNAL(inviteFriend(const QString &)), client, SLOT(inviteFriend(const QString &)));
	connect(mainWidget, SIGNAL(acceptInvitation(const QString &)), client, SLOT(acceptInvitation(const QString &)));
	connect(mainWidget, SIGNAL(denyInvitation(const QString &)), client, SLOT(denyInvitation(const QString &)));
}

void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason){
	switch (reason) {
		case QSystemTrayIcon::Context:
			trayIconMenu->show();
		break;
		default:
			if(!isVisible())
				restore();
			else{
				close();
			}
	}
}

void MainWindow::tryToConnect(const QString& login, const QString& password) {
	client = new Client::Client(host,port);
	mainWidget=new MainWidget(inactivityTime, this);

	createProtocolConnects();
	client->connect(login,password);
}

void MainWindow::connected(Friend *me){
	mainWidget->setMe(me);
	disconnectAction->setEnabled(true);
	registrationAction->setDisabled(true);
	setCentralWidget(mainWidget);
}

void MainWindow::cancelConnection() {
	delete client;
	QObject::disconnect(login,SIGNAL(cancelConnection()),this,SLOT(cancelConnection()));
}

void MainWindow::refused() {
	QObject::disconnect(client, SIGNAL(CAccepted(Friend *)), this, SLOT(connected(Friend *)));
	QObject::disconnect(client, SIGNAL(CDenied()), this, SLOT(refused()));
//	QObject::disconnect(client, SIGNAL(CDenied()), this->login, SLOT(refused()));
	QObject::disconnect(client, SIGNAL(UFFriendsList(QList<Friend *>)), this->mainWidget, SLOT(loadFriends(QList<Friend *>)));
	QObject::disconnect(mainWidget, SIGNAL(statusChanged(Status)), this, SLOT(statusChanged(Status)));

	delete mainWidget;
	mainWidget = 0;
}

void MainWindow::disconnect() {
	client->disconnect();
	delete client;
	client = 0;
	disconnected();
}

void MainWindow::disconnected() {
	createLogin();
	disconnectAction->setDisabled(true);
	registrationAction->setEnabled(true);
}

void MainWindow::restore() {
	this->show();
	restoreAction->setDisabled(true);
}

void MainWindow::config() {
	ConfigDialog *configDialog=new ConfigDialog(&host,&port,&inactivityTime,this);
	configDialog->show();
	if(mainWidget) mainWidget->setInactivityTime(inactivityTime);
	#warning configDialog deletion is missing
}

void MainWindow::registration() {
	RegistrationDialog *registrationDialog = new RegistrationDialog(this);
	registrationDialog->show();
	connect(registrationDialog,SIGNAL(registration(const QString &,const QString &)),this,SLOT(signup(const QString &,const QString &)));
}

void MainWindow::statusChanged(Status _status) {
	client->changeStatus(_status);
}

void MainWindow::signup(const QString &login,const QString &password) {
	client = new Client::Client(host,port);
	mainWidget=new MainWidget(inactivityTime,this);

	createProtocolConnects();
	client->signup(login,password);
}

}

